(function(b) {
	var a = {};
	a.config = {
		editable : true,
		tooltipAble:true,
		lineHeight : 18,
		contextPath : "",
		basePath : "",
		offsetX:90,
		offsetY:28,
		minWidth:600,
		minHeight:100,
		position:{
			minX:10000,
			minY:10000,
			maxX:0,
			maxY:0
		},
		tooltip:{
			width:300,
			height:200
		},
		tooltipCorn:{
			__width:20,
			__height:10
		},
		rect : {
			type : "state",
			showType : "image&text",
			attr : {
				x : 10,
				y : 10,
				width : 100,
				height : 50,
				r : 10,
				fill : "90-#CCCCCC-#f5f5f5",
				stroke : "#CCCCCC",
				"stroke-width" : 1
			},
			name : {
				text : "state",
				"font-style" : "italic",
				fill:"#FF0000"
			},
			taskCount:{
				text:{
					"cursor":"pointer",
					"font-style" : "italic",
					fill:"#FFFFFF"
				},
				bg:{
					r:10,
					width:20,
					height:20,
					_right:4,
					"cursor":"pointer",
					stroke : "#FFFFFF",
					"stroke-width" : 2,
					fill:"#5C9CF3"
				}
			},
			subCount:{
				text:{
					"cursor":"pointer",
					"font-style" : "italic",
					fill:"#FFFFFF"
				},
				bg:{
					r:10,
					width:20,
					height:20,
					_right:4,
					"cursor":"pointer",
					stroke : "#FFFFFF",
					"stroke-width" : 2,
					fill:"#5C9CF3"
				}
			},
			text : {
				text : "状态",
				"font-size" : 14
			},
			margin : 2,
			props : [],
			img : {}
		},
		path : {
			attr : {
				path : {
					path : "M10 10L100 100",
					stroke : "#CCCCCC",
					fill : "none",
					"stroke-width" : 2
				},
				arrow : {
					path : "M10 10L10 10",
					stroke : "#CCCCCC",
					fill : "#CCCCCC",
					"stroke-width" : 2,
					radius : 4
				},
				fromDot : {
					width : 5,
					height : 5,
					stroke : "#ffffff",
					fill : "#000000",
					cursor : "move",
					"stroke-width" : 2
				},
				toDot : {
					width : 5,
					height : 5,
					stroke : "#ffffff",
					fill : "#000000",
					cursor : "move",
					"stroke-width" : 2
				},
				bigDot : {
					width : 5,
					height : 5,
					stroke : "#ffffff",
					fill : "#000000",
					cursor : "move",
					"stroke-width" : 2
				},
				smallDot : {
					width : 5,
					height : 5,
					stroke : "#ffffff",
					fill : "#000000",
					cursor : "move",
					"stroke-width" : 3
				}
			},
			text : {
				// text : "TO {to}",
				text : "",
				cursor : "move",
				background : "#000000"
			},
			textPos : {
				x : 0,
				y : -10
			},
			props : {
				text : {
					name : "text",
					label : "显示",
					value : "",
					editor : function() {
						return new a.editors.textEditor();
					}
				}
			}
		},
		tools : {
			attr : {
				left : 0,
				top : 0
			},
			pointer : {},
			path : {},
			states : {},
			save : {
				onclick : function(c) {
				}
			}
		},
		props : {
			attr : {
				top : 0,
				right : 0
			},
			props : {}
		},
		restore : "",
		activeRects : {
			rects : [],
			rectAttr : {
				fill : "90-#FF9F64-#FFA26C",
				stroke : "#FBDDBB",
				"stroke-width" : 5,
				cursor:"pointer"
			},
			textAttr:{
				fill:"#FFFFFF",
				cursor:"pointer"
			},
			pathAttr : {
				path : {
					stroke : "#FF9F64"
				},
				arrow : {
					stroke : "#FF9F64",
					fill : "#FF9F64"
				}
			}
		},
		historyRects : {
			rects : [],
			rectAttr : {
				fill : "90-#96C22D-#A6CE59",
				stroke : "#D8E9B5",
				"stroke-width" : 5,
				cursor:"pointer"
			},
			textAttr:{
				fill:"#FFFFFF",
				cursor:"pointer"
			},
			pathAttr : {
				path : {
					stroke : "#B4D783"
				},
				arrow : {
					stroke : "#B4D783",
					fill : "#B4D783"
				}
			}
		},
		abendRects : {
			rects : [],
			rectAttr : {
				fill : "90-#FB766D-#FB766D",
				stroke : "#FB766D",
				"stroke-width" : 5,
				cursor:"pointer"
			},
			textAttr:{
				fill:"#FFFFFF",
				cursor:"pointer"
			},
			pathAttr : {
				path : {
					stroke : "#FB766D"
				},
				arrow : {
					stroke : "#FB766D",
					fill : "#FB766D"
				}
			}
		},
		subRects:{
			rects:[]
		}
	};
	a.util = {
		isLine : function(g, f, e) {
			var d, c;
			if ((g.x - e.x) == 0) {
				d = 1;
			} else {
				d = (g.y - e.y) / (g.x - e.x);
			}
			c = (f.x - e.x) * d + e.y;
			if ((f.y - c) < 10 && (f.y - c) > -10) {
				f.y = c;
				return true;
			}
			return false;
		},
		center : function(d, c) {
			return {
				x : (d.x - c.x) / 2 + c.x,
				y : (d.y - c.y) / 2 + c.y
			};
		},
		maxCount:0,
		nextId :function(id,prefix){
			// id=53fe db3d b2ee b23a c3f6 452b
			if(id){
				a.util.setMaxId(id,prefix);
				return id;
			}else{
				a.util.maxCount=a.util.maxCount+1;
				return prefix+a.util.maxCount;
			}
		}, 
		setMaxId:function(id,prefix){
			try {
				id=id.replace(prefix,'');
				var index=parseInt(id);
				if(isNaN(index)){
					index=a.util.maxCount+1;
				}
				a.util.maxCount=a.util.maxCount>index?a.util.maxCount:index;
			} catch (e) {
				a.util.maxCount=a.util.maxCount+1;
			}
		},
		connPoint : function(j, d) {
			var c = d, e = {
				x : j.x + j.width / 2,
				y : j.y + j.height / 2
			};
			
			var l = (e.y - c.y) / (e.x - c.x);
			l = isNaN(l) ? 0 : l;
			var k = j.height / j.width;
			var h = c.y < e.y ? -1 : 1, f = c.x < e.x ? -1 : 1, g, i;
			if (Math.abs(l) > k && h == -1) {
				g = e.y - j.height / 2;
				i = e.x + h * j.height / 2 / l;
			} else {
				if (Math.abs(l) > k && h == 1) {
					g = e.y + j.height / 2;
					i = e.x + h * j.height / 2 / l;
				} else {
					if (Math.abs(l) < k && f == -1) {
						g = e.y + f * j.width / 2 * l;
						i = e.x - j.width / 2;
					} else {
						if (Math.abs(l) < k && f == 1) {
							g = e.y + j.width / 2 * l;
							i = e.x + j.width / 2;
						}
					}
				}
			}
			return {
				x : i,
				y : g
			};
		},
		arrow : function(l, k, d) {
			var g = Math.atan2(l.y - k.y, k.x - l.x) * (180 / Math.PI);
			var h = k.x - d * Math.cos(g * (Math.PI / 180));
			var f = k.y + d * Math.sin(g * (Math.PI / 180));
			var e = h + d * Math.cos((g + 120) * (Math.PI / 180));
			var j = f - d * Math.sin((g + 120) * (Math.PI / 180));
			var c = h + d * Math.cos((g + 240) * (Math.PI / 180));
			var i = f - d * Math.sin((g + 240) * (Math.PI / 180));
			return [ k, {
				x : e,
				y : j
			}, {
				x : c,
				y : i
			} ];
		},
		createWFTitle:function(b,p,t){
			b(p).css("position","relative");
			var panel=b('<div class="title-panel">').appendTo(b(p));
			var text=b('<div class="title-panel-text">').text(t).appendTo(panel);
		},
		createTuLi:function(b,p){
			b(p).css("position","relative");
			var panel=b('<div class="tuli-panel">').appendTo(b(p));
			if(a.config.type=='task'){
				createTuLiItem(b,panel,"#FFA26C","表示进行中");
				createTuLiItem(b,panel,"#96C22D","表示已完成");
				createTuLiItem(b,panel,"#FB766D","表示异常");
			}else{
				createTuLiItem(b,panel,"#DDDDDD","表示未完成");
				createTuLiItem(b,panel,"#FFA26C","表示进行中");
				createTuLiItem(b,panel,"#96C22D","表示已完成");
				createTuLiItem(b,panel,"#FB766D","表示异常");
				createTuLiItem(b,panel,{"background":"#5C9CF3","border-radius":"10px"},"表示触发的子流程和任务");
			}
			
			function createTuLiItem(b,parent,c,t){
				var item=b("<div>").addClass("tuli-panel-item inline-block");
				var icon=b("<div>").addClass("tuli-panel-item-icon inline-block").html("&nbsp;");
				if(typeof c=="string"){
					icon.css("background",c);
				}else{
					icon.css(c);
				}
				var text=b("<div>").addClass("tuli-panel-item-text inline-block").text(t);
				item.append(icon).append(text).appendTo(parent);
			}
		},
		createDialog:function(b,node,data){
			var dialog=$(".myflow-dialog-panel");
			if(dialog.size()==0){
				var html=[];
				html.push('<div class="myflow-dialog-panel">');
				html.push('	<div class="myflow-dialog-panel-header">');
				html.push('		<div class="myflow-dialog-panel-title">');
				html.push('		</div>');
				html.push('   <img class="myflow-dialog-panel-close" src="'+a.config.basePath+'/img/close.png" />');
				html.push('	</div>');
				html.push('	<div class="myflow-dialog-panel-body">');
				html.push('   <iframe width="100%" height="100%" frameborder="0" />');
				html.push('	</div>');
				html.push('</div>');
				dialog=b(html.join(''));
				b("body").append(dialog);
			}
			var title=$(".myflow-dialog-panel-title",dialog);
			var iframe=$("iframe",dialog);
			var close=$(".myflow-dialog-panel-close",dialog);
			close.click(function(){
				dialog.hide();
			});
			title.text(data.text.text+"节点触发的子任务和子流程");
			iframe.attr("src",a.config.contextPath+"/view_child.jsp");
			dialog.show();
		}
	};
	a.rect = function(p, m,panel) {
		var flowId=a.config.flowId;
		var u = this, g = a.util.nextId(p.id,"rect"), E = b.extend(true, {}, a.config.rect, p), C = m, t, e, n, f, x, v,_type="normal",tc,sc;
		var subCount;// 触发的子的数量
		var toolTipData={};
		var panelSize=a.config.panelSize;
		if(a.config.stepDataRects){
			toolTipData=a.config.stepDataRects[g]||{};
		}
		if(E.props.projtype && !E.props.projtype.value){
			E.props.projtype.value=a.config.props.props.projtype.value;
		}
		if(E.props.formTemplate && !E.props.formTemplate.value){
			E.props.formTemplate.value=a.config.props.props.formTemplate.value;
		}
		if(E.props.approveTemplate && !E.props.approveTemplate.value){
			E.props.approveTemplate.value=a.config.props.props.approveTemplate.value;
		}
		if(!a.config.editable){
			E.attr.x=parseInt(E.attr.x)-parseInt(a.config.position.minX);
			E.attr.y=parseInt(E.attr.y)-parseInt(a.config.position.minY);
		}
		this.isCircle=function(){
			return E.type=='start'||E.type=='end'||E.type=='end-cancel'||E.type=='end-error';
		}
		this.isPolygon=function(){
			return E.type=='fork'||E.type=='join';
		}
		
		if(u.isPolygon()){
			t = C.diamond(E.attr.x, E.attr.y, E.attr.width, E.attr.height, E.attr.r).hide().attr(E.attr);
		}else if(u.isCircle()){
			t = C.circle(E.attr.x, E.attr.y, E.attr.width, E.attr.height, E.attr.r).hide().attr(E.attr);
			// t = C.rect(E.attr.x, E.attr.y, E.attr.width, E.attr.height,
			// E.attr.r).hide().attr(E.attr);
		}else{
			t = C.rect(E.attr.x, E.attr.y, E.attr.width, E.attr.height, E.attr.r).hide().attr(E.attr);
		}
		
		e = C.image(a.config.basePath + E.img.src, E.attr.x + E.img.width / 2, E.attr.y + (E.attr.height - E.img.height) / 2, E.img.width, E.img.height).hide();
		n = C.text(E.attr.x + E.img.width + (E.attr.width - E.img.width) / 2, E.attr.y + a.config.lineHeight / 2, E.name.text).hide().attr(E.name);
		
		f = C.text(E.attr.x + E.img.width + (E.attr.width - E.img.width) / 2, E.attr.y + (E.attr.height - a.config.lineHeight) / 2 + a.config.lineHeight, E.text.text).hide().attr(E.text);
		if (a.config.editable) {
			t.drag(function(r, o) {
				A(r, o);
			}, function() {
				z();
			}, function() {
				l();
			});
			e.drag(function(r, o) {
				A(r, o);
			}, function() {
				z();
			}, function() {
				l();
			});
			n.drag(function(r, o) {
				A(r, o);
			}, function() {
				z();
			}, function() {
				l();
			});
			f.drag(function(r, o) {
				A(r, o);
			}, function() {
				z();
			}, function() {
				l();
			});
		}
		var A = function(F, r) {
			if (!a.config.editable) {
				return
			}
			if(b(C).data("mod")=="path"){
				return;
			}
			var o = (x + F);
			var G = (v + r);
			q.x = o - E.margin;
			q.y = G - E.margin;
			B();
		};
		var z = function() {
			x = t.attr("x");
			v = t.attr("y");
			t.attr({
				opacity : 0.5
			});
			e.attr({
				opacity : 0.5
			});
			f.attr({
				opacity : 0.5
			});
		};
		var l = function() {
			t.attr({
				opacity : 1
			});
			e.attr({
				opacity : 1
			});
			f.attr({
				opacity : 1
			});
		};
		var s, i = {}, h = 5, q = {
			x : E.attr.x - E.margin,
			y : E.attr.y - E.margin,
			width : E.attr.width + E.margin * 2,
			height : E.attr.height + E.margin * 2
		};
		s = C.path("M0 0L1 1").hide();
		i.t = C.rect(0, 0, h, h).attr({
			fill : "#000000000",
			stroke : "#fffffffff",
			cursor : "s-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "t");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "t")
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		i.lt = C.rect(0, 0, h, h).attr({
			fill : "#000000",
			stroke : "#ffffff",
			cursor : "nw-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "lt");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "lt");
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		i.l = C.rect(0, 0, h, h).attr({
			fill : "#000000",
			stroke : "#ffffff",
			cursor : "w-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "l");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "l");
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		i.lb = C.rect(0, 0, h, h).attr({
			fill : "#000000",
			stroke : "#ffffff",
			cursor : "sw-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "lb");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "lb");
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		i.b = C.rect(0, 0, h, h).attr({
			fill : "#000000",
			stroke : "#ffffff",
			cursor : "s-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "b");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "b");
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		i.rb = C.rect(0, 0, h, h).attr({
			fill : "#000000",
			stroke : "#ffffff",
			cursor : "se-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "rb");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "rb");
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		i.r = C.rect(0, 0, h, h).attr({
			fill : "#000000",
			stroke : "#ffffff",
			cursor : "w-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "r");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "r");
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		i.rt = C.rect(0, 0, h, h).attr({
			fill : "#000000",
			stroke : "#ffffff",
			cursor : "ne-resize"
		}).hide().drag(function(r, o) {
			D(r, o, "rt");
		}, function() {
			k(this.attr("x") + h / 2, this.attr("y") + h / 2, "rt");
		}, function() {
			E.attr.width=q.width;
			E.attr.height=q.height;
			u.restore(E);
		});
		var D = function(F, r, G) {
			if (!a.config.editable) {
				return
			}
			var o = _bx + F, H = _by + r;
			switch (G) {
			case "t":
				q.height += q.y - H;
				q.y = H;
				break;
			case "lt":
				q.width += q.x - o;
				q.height += q.y - H;
				q.x = o;
				q.y = H;
				break;
			case "l":
				q.width += q.x - o;
				q.x = o;
				break;
			case "lb":
				q.height = H - q.y;
				q.width += q.x - o;
				q.x = o;
				break;
			case "b":
				q.height = H - q.y;
				break;
			case "rb":
				q.height = H - q.y;
				q.width = o - q.x;
				break;
			case "r":
				q.width = o - q.x;
				break;
			case "rt":
				q.width = o - q.x;
				q.height += q.y - H;
				q.y = H;
				break;
			}
			B();
		};
		var k = function(r, o, F) {
			_bx = r;
			_by = o;
		};
		// tooltip
		var _st=function(event,src,node){
			var tooltip,corn,data=toolTipData;
			tooltip=b(src).data("tooltip");
			// caret 分离的原因是由于 这样可以不管三角形与节点对应
			if(!tooltip){
				tooltip=b('<div class="state-tooltip state-tooltip-hide-able">').hide();
				corn=b('<div class="state-tooltip-corn"><div class="state-tooltip-corn-inner"></div></div>').hide();
				tooltip.data("corn",corn);
				b(src).data("tooltip",tooltip);
				b(panel).append(tooltip).append(corn);
				
				var title=b('<div class="state-tooltip-title">').text(data.description||node.getData().props.name.value);
				tooltip.append(title);
				var content=b('<div class="state-tooltip-content">');
				tooltip.append(content);
				var _type=node.getWFType();
				var html=[];
				html.push('');
				html.push('<table class="tooltip-table" cellpadding="0" cellspacing="0">');
				html.push('		<tr>');
				html.push('			<td align="left" class="tooltip-table-label"  width="110" height="30">截止时间：</td>');
				html.push('			<td>'+(data['limit_date_time']||"-")+'</td>');
				html.push('		</tr>');
				html.push('		<tr>');
				html.push('			<td align="left" class="tooltip-table-label"   height="30">工作时限(小时)：</td>');
				html.push('			<td>'+(data['workTime']||"-")+'</td>');
				html.push('		</tr>');
				html.push('		<tr>');
				html.push('			<td align="left" class="tooltip-table-label"   height="20">执行人员</td>');
				html.push('			<td colspan="3">&nbsp;</td>');
				html.push('		</tr>');
				html.push('		<tr>');
				html.push('			<td colspan="4" valign="top">');
				html.push('<table class="tooltip-item-table" cellpadding="0" cellspacing="0" width="100%">');
				html.push('	  <thead>');
				html.push('		<tr>');
				if(a.config.type=="workflow"){
					html.push('		<th width="40">姓名</th>');
					html.push('		<th>部门</th>');
					html.push('     <th width="70">意见</th>');
					html.push('		<th width="80">完成时间</th>');
				}else{
					html.push('		<th width="60">姓名</th>');
					html.push('		<th>部门</th>');
					html.push('		<th width="90">完成时间</th>');
				}
				
				html.push('		</tr>');
				html.push('	  </thead>');
				html.push('	  <tbody>');
				if(data['userData'] && data['userData'].length){
					for(var i in data['userData'] ){
						var item=data['userData'][i];
						html.push('		<tr>');
						html.push('		<td>'+(item.fullname||"-")+'</td>');
						html.push('		<td align="center">'+(item.org_name||"-")+'</td>');
						if(a.config.type=="workflow"){
							html.push('		<td align="center">'+(item.action||"-")+'</td>');
						}
						html.push('		<td align="center">'+(item.approve_time||"-")+'</td>');
						html.push('		</tr>');
					}
				}else{
					html.push('		<tr>');
					html.push('		<td colspan="4">无数据</td>');
					html.push('		</tr>');
				}
				html.push('	  </tbody>');
				html.push('</table>');
				html.push('			</td>');
				html.push('		</tr>');
				html.push('</table>');
				content.html(html.join(''));
			}else{
				corn=tooltip.data("corn");
				if(!corn){
					corn=b('<div class="state-tooltip-corn"><div class="state-tooltip-corn-inner"></div></div>').hide();
					tooltip.data("corn",corn);
					b(a.config.mainPanel).append(corn);
				};
			}
			var pos=node.getBBox();
			// pos.x=pos.x+b(panel).offset().left;
			// pos.y=pos.y+b(panel).offset().top;
			var size=panelSize;
			var _offTop=6;
			if(pos.y>a.config.tooltip.height-_offTop){
				// top
				a.config.tooltip.top=pos.y-a.config.tooltip.height-_offTop;
				a.config.tooltip.left=pos.x+pos.width/2-a.config.tooltip.width/2;
				
				a.config.tooltipCorn.top=a.config.tooltip.top+a.config.tooltip.height+1;
				a.config.tooltipCorn.left=pos.x+pos.width/2-a.config.tooltipCorn.__width/2;
				corn.addClass("state-tooltip-corn-bottom");
			}else{
				// bottom
				a.config.tooltip.top=pos.y+pos.height+_offTop;
				a.config.tooltip.left=pos.x+pos.width/2-a.config.tooltip.width/2;
				
				a.config.tooltipCorn.top=a.config.tooltip.top-a.config.tooltipCorn.__height;
				a.config.tooltipCorn.left=pos.x+pos.width/2-a.config.tooltipCorn.__width/2;
				
				corn.addClass("state-tooltip-corn-top");
			}
			
			var minLeft=20;
			var maxRight=size.width-minLeft-a.config.tooltip.width;
			if(a.config.tooltip.left<minLeft){
				a.config.tooltip.left=minLeft;
			}else if(a.config.tooltip.left>maxRight){
				a.config.tooltip.left=maxRight;
			}
			
			tooltip.css(a.config.tooltip).show();
			corn.css(a.config.tooltipCorn).show();
			var _t_1;
			tooltip.hover(function(){
				if(_t_1){
					window.clearTimeout(_t_1);
				}
				tooltip.removeClass("state-tooltip-hide-able");
			},function(){
				tooltip.addClass("state-tooltip-hide-able");
				if(_t_1){
					window.clearTimeout(_t_1);
				}
				_t_1=window.setTimeout(function(){
					b(src).trigger("hideTooltip", [src,node]);
				}, 300);
			});
		};
		var _ht=function(event,src,node){
			var tooltip=b(src).data("tooltip");
			if(tooltip && tooltip.hasClass("state-tooltip-hide-able")){
				tooltip.hide();
				var corn=tooltip.data("corn");
				if(corn){
					corn.hide();
				}
			}
		};
		if(E.type=='task'||E.type=='state'){
			b(t.node).bind("showTooltip", _st);
			b(t.node).bind("hideTooltip", _ht);
		}
		var _t_t_l;
		b([ t.node, f.node, n.node, e.node ]).bind("mouseover", function() {
			if (a.config.editable||!a.config.tooltipAble) {
				return
			}
			b(t.node).attr("waiting-tooltip",true);
			if(_t_t_l){
				window.clearTimeout(_t_t_l);
			}
			_t_t_l=window.setTimeout(function(){
				if(b(t.node).attr("waiting-tooltip")){
					b(t.node).trigger("showTooltip", [t.node,u]);
				}
			}, 200);
			return false;
		}).bind("mouseout",function(){
			b(t.node).removeAttr("waiting-tooltip");
			if(_t_t_l){
				window.clearTimeout(_t_t_l);
				_t_t_l=window.setTimeout(function(){
					b(t.node).trigger("hideTooltip", [t.node,u]);
				}, 300);
			}
		}).bind("click",function(){
			if (a.config.editable||!a.config.tooltipAble) {
				return
			}
			b(t.node).trigger("showTooltip", [t.node,u]);
		});
		
// if (!a.config.editable && a.config.type != 'task') {
// b([ t.node, f.node, n.node, e.node ]).bind("dblclick",function(){
// try {
// if(_type != 'normal'){
// parent.showFormData(u,flowId,g);
// }
// } catch (e) {
// if(console){
// console.log(e);
// }
// alert('查看表单失败.');
// }
// return false;
// });
// }
		b([ t.node, f.node, n.node, e.node ]).bind("mousedown", function() {
			if (!a.config.editable) {
				return
			}
			if(b(C).data("mod")=="pointer"){
				w();
				b([ t.node, f.node, n.node, e.node ]).css("cursor","move");
			}
			b(C).trigger("click", u);
			b(C).data("mousedownNode", u);
			return false;
		});
		b([ t.node, f.node, n.node, e.node ]).bind("mouseup", function() {
			if (!a.config.editable) {
				return
			}
			if(b(C).data("mod")=="path"){
				var r = b(C).data("mousedownNode");
				if (r && r.getId() != g && r.getId().substring(0, 4) == "rect") {
					b(C).trigger("addpath", [ r, u ]);
				}
			}
		});
		b([ t.node, f.node, n.node, e.node ]).bind("click", function() {
			b(C).data("currNode", u);
			b(C).data("mousedownNode", u);
			if (!a.config.editable) {
				return
			}
			b(C).trigger("click", u);
			return false;
		});
		var j = function(o, r) {
			if (!a.config.editable) {
				return
			}
			if (r.getId() == g) {
				 b(C).trigger("showprops", [ E.props, r  ]);
			} else {
				d();
			}
		};
	
		b(C).bind("click", j);
		var c = function(o, F, r,_t) {
			if (r.getId() == g) {
				E.text.text=F;
				r.restore(E);
			}
		};
		b(C).bind("textchange", c);
		
		function y() {
			return "M" + q.x + " " + q.y + "L" + q.x + " " + (q.y + q.height) + "L" + (q.x + q.width) + " " + (q.y + q.height) + "L" + (q.x + q.width) + " " + q.y + "L" + q.x
					+ " " + q.y;
		}
		function w() {
			s.show();
			for ( var o in i) {
				i[o].show();
			}
		}
		function d() {
			s.hide();
			b([ t.node, f.node, n.node, e.node ]).css("cursor","inherit");
			for ( var o in i) {
				i[o].hide();
			}
		}
		function B() {
			var F = q.x + E.margin, r = q.y + E.margin, G = q.width - E.margin * 2, o = q.height - E.margin * 2;
			var attrs={};
			if(u.isCircle()){
				var temp=myUtil.min(G,o);
				G=o=temp;
				attrs["cx"]=F+G/2;
				attrs["cy"]=r+o/2;
				attrs["r"]=temp/2;
			}else if(u.isPolygon()){
				attrs["points"] =myUtil.getPolygonPoints(F,r,G,o);
			}
			
			attrs["x"]=F;
			attrs["y"]=r;
			attrs["rx"]=F;
			attrs["ry"]=r;
			attrs["width"]=G;
			attrs["height"]=o;
			
			t.attr(attrs);
			switch (E.showType) {
			case "image":
				e.attr({
					x : F + (G - E.img.width) / 2,
					y : r + (o - E.img.height) / 2
				}).show();
				break;
			case "text":
				t.show();
				f.attr({
					x : F + G / 2,
					y : r + o / 2
				}).show();
				break;
			case "image&text":
				t.show();
				n.attr({
					x : F + E.img.width + (G - E.img.width) / 2,
					y : r + a.config.lineHeight / 2
				}).show();
				f.attr({
					x : F + E.img.width + (G - E.img.width) / 2,
					y : r + (o - a.config.lineHeight) / 2 + a.config.lineHeight
				}).show();
				e.attr({
					x : F + E.img.width / 2,
					y : r + (o - E.img.height) / 2
				}).show();
				break
			}
			i.t.attr({
				x : q.x + q.width / 2 - h / 2,
				y : q.y - h / 2
			});
			i.lt.attr({
				x : q.x - h / 2,
				y : q.y - h / 2
			});
			i.l.attr({
				x : q.x - h / 2,
				y : q.y - h / 2 + q.height / 2
			});
			i.lb.attr({
				x : q.x - h / 2,
				y : q.y - h / 2 + q.height
			});
			i.b.attr({
				x : q.x - h / 2 + q.width / 2,
				y : q.y - h / 2 + q.height
			});
			i.rb.attr({
				x : q.x - h / 2 + q.width,
				y : q.y - h / 2 + q.height
			});
			i.r.attr({
				x : q.x - h / 2 + q.width,
				y : q.y - h / 2 + q.height / 2
			});
			i.rt.attr({
				x : q.x - h / 2 + q.width,
				y : q.y - h / 2
			});
			s.attr({
				path : y()
			});
			b(C).trigger("rectresize", u);
		}
		this.rebuildSub=function(sub){
			// var _x1=E.attr.x +
			// E.attr.width-E.taskCount.bg.width-E.taskCount.bg._right;
			// var _y1=E.attr.y + (E.attr.height/2-E.taskCount.bg.height);
			var _x1=E.attr.x + E.attr.width-E.taskCount.bg.width/2;
			var _y1=E.attr.y - E.taskCount.bg.height/2;
			
		// var _x2=E.attr.x +
		// E.attr.width-E.subCount.bg.width-E.taskCount.bg._right;
		// var _y2=E.attr.y +
		// E.attr.height/2+(E.attr.height/2-E.subCount.bg.height)/2;
			
			tcbg = C.rect(_x1,_y1, E.taskCount.bg.r).hide().attr(E.taskCount.bg);
		// scbg = C.rect(_x2, _y2, E.subCount.bg.r).hide().attr(E.subCount.bg);
			
			tc = C.text(_x1+E.taskCount.bg.width/2 , _y1+E.taskCount.bg.height/2).hide().attr(E.taskCount.text);
		// sc = C.text(_x2+E.subCount.bg.width/2 ,
		// _y2+E.subCount.bg.height/2).hide().attr(E.subCount.text);
			
			// b([tcbg.node,tc.node,scbg.node,sc.node]).bind("click",function(){
			b([tcbg.node,tc.node]).bind("click",function(){
				// a.util.createDialog(b,u,E);
				loadFlowSubData(u,flowId);
			});
			subCount=0;
			if(sub.taskCount){
				subCount+=parseInt(sub.taskCount);
			}
			if(sub.subCount){
				subCount+=parseInt(sub.subCount);
			}
			this.restore(E);
		};
		this.toJson = function() {
			a.config.position.minX=myUtil.min(a.config.position.minX, Math.round(t.attr("x")));
			a.config.position.minY=myUtil.min(a.config.position.minY, Math.round(t.attr("y")));
			a.config.position.maxX=myUtil.max(a.config.position.maxX, Math.round(t.attr("x"))+ Math.round(t.attr("width")));
			a.config.position.maxY=myUtil.max(a.config.position.maxY, Math.round(t.attr("y"))+ Math.round(t.attr("height")));
			
			var r = "{'type':'" + E.type + "','text':{'text':'" + E.text.text + "'}, 'attr':{ 'x':" + Math.round(t.attr("x")) + ", 'y':" + Math.round(t.attr("y")) + ", 'width':"
					+ Math.round(t.attr("width")) + ", 'height':" + Math.round(t.attr("height")) + "}, 'props':{";
			for ( var o in E.props) {
				var val=E.props[o].value;
				if(typeof val=="object"){
					r += "'"+o + "':{'value':" + myUtil.jsonArrayToString(val)+ "},"
				}else{
					r +="'"+ o + "':{'value':'" + val+ "'},"
				}
			}
			if (r.substring(r.length - 1, r.length) == ",") {
				r = r.substring(0, r.length - 1)
			}
			r += "}}";
			return r;
		};
		this.mousedown=function(){
			b(t.node).mousedown();
		};
		this.restore = function(o) {
			var r = o;
			E = b.extend(true, E, o);
			if(!a.config.editable){
				E.attr.x=parseInt(E.attr.x)-parseInt(a.config.position.minX);
				E.attr.y=parseInt(E.attr.y)-parseInt(a.config.position.minY);
			}
			var _w=0;// 计算右边的提示宽度
			
			if(subCount>0){
				tc.attr({
					text:subCount
				})
				b(tcbg.node).show();
				b(tc.node).show();
				// _w=24;
			}
			f.attr({
				text : this.getMoreLineText(o.attr.width, r.text.text,_w)
			});
			B();
		};
		this.getMoreLineText=function(width,text,_w){
			var _width=14;// 单个字符宽度
			var _off=_w;
			if(E.showType!="text"){
				_off=_off+E.img.width +12;
			}
			var _l=parseInt((parseInt(width)-_off)/_width-0.5);
			var newText=text;
			if(newText){
				var _arr=newText.split('');
				newText="";
				var _index=0;
				for(var i in _arr){
					var _c=_arr[i];
					if(_index>1 && parseInt(_index)%_l==0){
						newText=newText+"\n";
					}
					newText=newText+_c;
					if(/^[\u4e00-\u9fa5]+$/.test(_c)){
						_index=_index+1;
					}else{
						_index=_index+0.5;
					}
				}
			}
			return newText;
		};
		this.getFormType=function(){
			return E.props.projtype.value;
		};
		this.getBBox = function() {
			return q
		};
		this.getId = function() {
			return g
		};
		this.remove = function() {
			t.remove();
			f.remove();
			n.remove();
			e.remove();
			s.remove();
			for ( var o in i) {
				i[o].remove()
			}
		};
		this.text = function() {
			return f.attr("text")
		};
		this.attr = function(o) {
			if (o) {
				t.attr(o);
			}
		};
		this.textAttr = function(o) {
			if (o) {
				f.attr(o);
			}
		};
		this.setWFType=function(type){
			_type=type;
		};
		this.getWFType=function(){
			return _type;
		};
		this.getData=function(){
			return E;
		}
		this.freshAlways=function(){
			return E.freshAlways;
		}
		B()
	};
	a.path = function(q, n, u, e) {
		var v = this, z = n, B = b.extend(true, {}, a.config.path), i, t, f, h = B.textPos, y, w, k = u, s = e, g = a.util.nextId(q.id,"path"), x;
		function p(G, H, D, L) {
			var F = this, M = G, r, o = D, O = L, K, I, N = H;
			switch (M) {
			case "from":
				r = z.rect(H.x - B.attr.fromDot.width / 2, H.y - B.attr.fromDot.height / 2, B.attr.fromDot.width, B.attr.fromDot.height).attr(B.attr.fromDot);
				break;
			case "big":
				r = z.rect(H.x - B.attr.bigDot.width / 2, H.y - B.attr.bigDot.height / 2, B.attr.bigDot.width, B.attr.bigDot.height).attr(B.attr.bigDot);
				break;
			case "small":
				r = z.rect(H.x - B.attr.smallDot.width / 2, H.y - B.attr.smallDot.height / 2, B.attr.smallDot.width, B.attr.smallDot.height).attr(B.attr.smallDot);
				break;
			case "to":
				r = z.rect(H.x - B.attr.toDot.width / 2, H.y - B.attr.toDot.height / 2, B.attr.toDot.width, B.attr.toDot.height).attr(B.attr.toDot);
				break
			}
			if (r && (M == "big" || M == "small")||true) {
				r.drag(function(Q, P) {
					C(Q, P)
				}, function() {
					J()
				}, function() {
					E()
				});
				var C = function(R, Q) {
					var P = (K + R), S = (I + Q);
					F.moveTo(P, S)
				};
				var J = function() {
					if (M == "big") {
						K = r.attr("x") + B.attr.bigDot.width / 2;
						I = r.attr("y") + B.attr.bigDot.height / 2
					}
					if (M == "small") {
						K = r.attr("x") + B.attr.smallDot.width / 2;
						I = r.attr("y") + B.attr.smallDot.height / 2
					}
					K = r.attr("x") + B.attr.smallDot.width / 2;
					I = r.attr("y") + B.attr.smallDot.height / 2
				};
				var E = function() {
				}
			}
			this.type = function(P) {
				if (P) {
					M = P
				} else {
					return M
				}
			};
			this.node = function(P) {
				if (P) {
					r = P
				} else {
					return r
				}
			};
			this.left = function(P) {
				if (P) {
					o = P
				} else {
					return o
				}
			};
			this.right = function(P) {
				if (P) {
					O = P
				} else {
					return O
				}
			};
			this.remove = function() {
				o = null;
				O = null;
				r.remove()
			};
			this.pos = function(P) {
				if (P) {
					N = P;
					r.attr({
						x : N.x - r.attr("width") / 2,
						y : N.y - r.attr("height") / 2
					});
					return this
				} else {
					return N
				}
			};
			this.moveTo = function(Q, T) {
				this.pos({
					x : Q,
					y : T
				});
				switch (M) {
				case "from":
					if (O && O.right() && O.right().type() == "to") {
						O.right().pos(a.util.connPoint(s.getBBox(), N))
					}
					if (O && O.right()) {
						O.pos(a.util.center(N, O.right().pos()))
					}
					break;
				case "big":
					if (O && O.right() && O.right().type() == "to") {
						O.right().pos(a.util.connPoint(s.getBBox(), N))
					}
					if (o && o.left() && o.left().type() == "from") {
						o.left().pos(a.util.connPoint(k.getBBox(), N))
					}
					if (O && O.right()) {
						O.pos(a.util.center(N, O.right().pos()))
					}
					if (o && o.left()) {
						o.pos(a.util.center(N, o.left().pos()))
					}
					var S = {
						x : N.x,
						y : N.y
					};
					if (a.util.isLine(o.left().pos(), S, O.right().pos())) {
						M = "small";
						r.attr(B.attr.smallDot);
						this.pos(S);
						var P = o;
						o.left().right(o.right());
						o = o.left();
						P.remove();
						var R = O;
						O.right().left(O.left());
						O = O.right();
						R.remove()
					}
					break;
				case "small":
					if (o && O && !a.util.isLine(o.pos(), {
						x : N.x,
						y : N.y
					}, O.pos())) {
						M = "big";
						r.attr(B.attr.bigDot);
						var P = new p("small", a.util.center(o.pos(), N), o, o.right());
						o.right(P);
						o = P;
						var R = new p("small", a.util.center(O.pos(), N), O.left(), O);
						O.left(R);
						O = R
					}
					break;
				case "to":
					if (o && o.left() && o.left().type() == "from") {
						o.left().pos(a.util.connPoint(k.getBBox(), N))
					}
					if (o && o.left()) {
						o.pos(a.util.center(N, o.left().pos()))
					}
					break
				}
				m()
			}
		}
		
		function j() {
			var D, C, E = k.getBBox(), F = s.getBBox(), r, o;
			r = a.util.connPoint(E, {
				x : F.x + F.width / 2,
				y : F.y + F.height / 2
			});
			o = a.util.connPoint(F, r);
			D = new p("from", r, null, new p("small", {
				x : (r.x + o.x) / 2,
				y : (r.y + o.y) / 2
			}));
			D.right().left(D);
			C = new p("to", o, D.right(), null);
			D.right().right(C);
			this.toPathString = function() {
				if (!D) {
					return ""
				}
				var J = D, I = "M" + J.pos().x + " " + J.pos().y, H = "";
				while (J.right()) {
					J = J.right();
					I += "L" + J.pos().x + " " + J.pos().y
				}
				var G = a.util.arrow(J.left().pos(), J.pos(), B.attr.arrow.radius);
				H = "M" + G[0].x + " " + G[0].y + "L" + G[1].x + " " + G[1].y + "L" + G[2].x + " " + G[2].y + "z";
				return [ I, H ]
			};
			this.toJson = function() {
				var G = "[", H = D;
				while (H) {
					a.config.position.minX=myUtil.min(a.config.position.minX, Math.round(H.pos().x));
					a.config.position.minY=myUtil.min(a.config.position.minY, Math.round(H.pos().y));
					a.config.position.maxX=myUtil.max(a.config.position.maxX, Math.round(H.pos().x));
					a.config.position.maxY=myUtil.max(a.config.position.maxY, Math.round(H.pos().y));
					if (H.type() == "big") {
						G += "{'x':" + Math.round(H.pos().x) + ",'y':" + Math.round(H.pos().y) + "},"
					}
					H = H.right()
				}
				if (G.substring(G.length - 1, G.length) == ",") {
					G = G.substring(0, G.length - 1)
				}
				G += "]";
				return G
			};
			this.restore = function(H) {
				var I = H, J = D.right();
				for (var G = 0; G < I.length; G++) {
					J.moveTo(I[G].x, I[G].y);
					J.moveTo(I[G].x, I[G].y);
					J = J.right()
				}
				this.hide()
			};
			this.fromDot = function() {
				return D
			};
			this.toDot = function() {
				return C
			};
			this.midDot = function() {
				var H = D.right(), G = D.right().right();
				while (G.right() && G.right().right()) {
					G = G.right().right();
					H = H.right()
				}
				return H
			};
			this.show = function() {
				var G = D;
				while (G) {
					G.node().show();
					G = G.right()
				}
			};
			this.hide = function() {
				var G = D;
				while (G) {
					G.node().hide();
					G = G.right()
				}
			};
			this.remove = function() {
				var G = D;
				while (G) {
					if (G.right()) {
						G = G.right();
						G.left().remove()
					} else {
						G.remove();
						G = null
					}
				}
			}
		}
		B = b.extend(true, B, q);
		i = z.path(B.attr.path.path).attr(B.attr.path);
		t = z.path(B.attr.arrow.path).attr(B.attr.arrow);
		x = new j();
		x.hide();
		f = z.text(0, 0, B.text.text).attr(B.text).attr({
			// text : B.text.text.replace("{from}", k.text()).replace("{to}",
			// s.text())
		});// .hide();
		f.drag(function(r, o) {
			if (!a.config.editable) {
				return
			}
			f.attr({
				x : y + r,
				y : w + o
			})
		}, function() {
			y = f.attr("x");
			w = f.attr("y")
		}, function() {
			var o = x.midDot().pos();
			h = {
				x : f.attr("x") - o.x,
				y : f.attr("y") - o.y
			}
		});
		m();
		b([ i.node, t.node,f.node ]).bind("mousedown", function() {
			if (!a.config.editable) {
				return
			}
			b(z).trigger("click", v);
			b(z).data("mousedownNode", v);
			return false
		});
		b([ i.node, t.node,f.node ]).bind("click", function() {
			if (!a.config.editable) {
				return
			}
			b(z).trigger("click", v);
			b(z).data("currNode", v);
			b(z).data("mousedownNode", v);
			return false
		});
		var l = function(r, C) {
			if (!a.config.editable) {
				return
			}
			if (C && C.getId() == g) {
				 x.show();
				 b(z).trigger("showprops", [ B.props, v ])
			} else {
				x.hide()
			}
			var o = b(z).data("mod");
			switch (o) {
			case "pointer":
				break;
			case "path":
				break
			}
		};
		b(z).bind("click", l);
		var A = function(o, r) {
			if (!a.config.editable) {
				return
			}
			if (r && (r.getId() == k.getId() || r.getId() == s.getId())) {
				b(z).trigger("removepath", v)
			}
		};
		b(z).bind("removerect", A);
		var d = function(C, D) {
			if (!a.config.editable) {
				return
			}
			if (k && k.getId() == D.getId()) {
				var o;
				if (x.fromDot().right().right().type() == "to") {
					o = {
						x : s.getBBox().x + s.getBBox().width / 2,
						y : s.getBBox().y + s.getBBox().height / 2
					}
				} else {
					o = x.fromDot().right().right().pos()
				}
				var r = a.util.connPoint(k.getBBox(), o);
				x.fromDot().moveTo(r.x, r.y);
				m()
			}
			if (s && s.getId() == D.getId()) {
				var o;
				if (x.toDot().left().left().type() == "from") {
					o = {
						x : k.getBBox().x + k.getBBox().width / 2,
						y : k.getBBox().y + k.getBBox().height / 2
					}
				} else {
					o = x.toDot().left().left().pos()
				}
				var r = a.util.connPoint(s.getBBox(), o);
				x.toDot().moveTo(r.x, r.y);
				m()
			}
		};
		b(z).bind("rectresize", d);
		var c = function(r, o, C) {
			if (C.getId() == g) {
				f.attr({
					text : o
				})
			}
		};
		b(z).bind("textchange", c);
		this.mousedown=function(){
			b(i.node).mousedown();
		};
		this.from = function() {
			return k
		};
		this.to = function() {
			return s
		};
		this.getFormType=function(){
			return s.getData().props.projtype.value;
		};
		this.toJson = function() {
			var r = "{'from':'" + k.getId() + "','to':'" + s.getId() + "', 'dots':" + x.toJson() + ",'text':{'text':'" + f.attr("text") + "'},'textPos':{'x':" + Math.round(h.x) + ",'y':"
					+ Math.round(h.y) + "}, 'props':{";
			for ( var o in B.props) {
				var val=B.props[o].value;
				if(typeof val=="object"){
					r += o + ":{'value':" + myUtil.jsonArrayToString(val)+ "},"
				}else{
					r += o + ":{'value':'" + val+ "'},"
				}
			}
			if (r.substring(r.length - 1, r.length) == ",") {
				r = r.substring(0, r.length - 1)
			}
			r += "}}";
			return r
		};
		this.restore = function(o) {
			var r = o;
			B = b.extend(true, B, o);
			if(!a.config.editable && B.dots){
				var l=B.dots.length;
				for(var i=0;i<l;i++){
					B.dots[i].x=parseInt(B.dots[i].x)-parseInt(a.config.position.minX);
					B.dots[i].y=parseInt(B.dots[i].y)-parseInt(a.config.position.minY);
				}
			}
			x.restore(B.dots)
		};
		this.remove = function() {
			x.remove();
			i.remove();
			t.remove();
			f.remove();
			try {
				b(z).unbind("click", l)
			} catch (o) {
			}
			try {
				b(z).unbind("removerect", A)
			} catch (o) {
			}
			try {
				b(z).unbind("rectresize", d)
			} catch (o) {
			}
			try {
				b(z).unbind("textchange", c)
			} catch (o) {
			}
		};
		function m() {
			var r = x.toPathString(), o = x.midDot().pos();
			i.attr({
				path : r[0]
			});
			t.attr({
				path : r[1]
			});
			f.attr({
				x : o.x + h.x,
				y : o.y + h.y
			})
		}
		this.getId = function() {
			return g
		};
		this.text = function() {
			return f.attr("text")
		};
		this.attr = function(o) {
			if (o && o.path) {
				i.attr(o.path)
			}
			if (o && o.arrow) {
				t.attr(o.arrow)
			}
		}
	};
	a.props = function(h, f) {
		var j = this, c = b("#myflow_props"), e = c.find("table tbody").empty(), g = f, i;
		var _m,_o;
		var d = function(n, m, o) {
			if (i && i.getId() == o.getId()) {
				return
			}
			i = o;
			_m=m;
			_o=o;
			
			b(g).trigger("saveprops", [ m, o]);
			b(g).trigger("showpropsByUI", [ m, o]);
		};
		
		var u = function(n, m, o) {
			e.empty();
			c.show();
			for ( var l in m) {
				if (m[l].label) {
					e.append('<tr><th align="justify"  width="60">' + m[l].label + '</th><td><div id="p' + l + '" class="editor"></div></td></tr>');
					if (m[l].editor) {
						m[l].editor().init(m, l, "p" + l, o, g);
					}
				}
			}
		};
		var s=function(n, m, o) {
			b(e).find(".editor").each(function() {
				var k = b(this).data("editor");
				if (k) {
					k.destroy();
				}
			});
		}
		b(g).bind("showprops", d);
		b(g).bind("showpropsByUI", u);
		b(g).bind("saveprops", s);
		 // b(document).click();
		this.freshByUI=function(){
			b(g).trigger("showpropsByUI", [_m,_o]);
		}
	};
	a.editors = {
		textEditor : function() {
			var d, e, c, g, f;
			this.init = function(i, h, m, l, j) {
				d = i;
				e = h;
				c = m;
				g = l;
				f = j;
				b('<input  style="width:100%;"/>').val(g.text()).change(function() {
					i[e].value = b(this).val();
					b(f).trigger("textchange", [ b(this).val(), g ]);
				}).appendTo("#" + c);
				b("#" + c).data("editor", this)
			};
			this.destroy = function() {
				b("#" + c + " input").each(function() {
					d[e].value = b(this).val();
					b(f).trigger("textchange", [ b(this).val(), g ])
				})
			}
		}
	};
	a.init = function(x, r) {
		var v = b(window).width()||1000, e = b(window).height()||600,  q = {}, g = {},_props;
		if(typeof r.restore !="object"){
			r.restore=myUtil.stringToJson(r.restore);
		}
		if(typeof r.activeRects !="object"){
			r.activeRects=myUtil.stringToJson(r.activeRects);
		}
		if(typeof r.historyRects !="object"){
			r.historyRects=myUtil.stringToJson(r.historyRects);
		}
		if(typeof r.abendRects !="object"){
			r.abendRects=myUtil.stringToJson(r.abendRects);
		}
		if(typeof r.subRects !="object"){
			r.subRects=myUtil.stringToJson(r.subRects);
		}
		if(typeof r.stepDataRects !="object"){
			r.stepDataRects=myUtil.stringToJson(r.stepDataRects);
		}
		a.config.activeRects.rects=[];
		a.config.historyRects.rects=[];
		a.config.abendRects.rects=[];
		a.config.subRects.rects=[];
		a.config.stepDataRects={};
		
		b.extend(true, a.config, r);
		if(r.restore &&r.restore.props){
			b.extend(true, a.config.props.props, r.restore.props.props);
		}
		a.util.maxCount=0;// 初始化ID
		// 初始化面板
		var _w,_h;
		if (a.config.editable || !r.restore.position) {
			 _w=v*3;
			 _h=v*5;
		}else{
			_w=(parseInt(r.restore.position.maxX)-parseInt(r.restore.position.minX))+20*2;
			_h=(parseInt(r.restore.position.maxY)-parseInt(r.restore.position.minY))+50*2;
			
			// 出去流程标题
			r.restore.position.minY=parseInt(r.restore.position.minY)-50;
			r.restore.position.minX=parseInt(r.restore.position.minX)-20;
			

			_w=myUtil.max(a.config.minWidth, _w);
			_h=myUtil.max(a.config.minHeight, _h);
			
			window["max_flow_width"]=myUtil.max(window["max_flow_width"], _w);
			/*
			 * b(x).css({ height:_h })
			 */
			// TODO
			b(".workflow-box").css({
			// width:window["max_flow_width"]
			})
			// 初始化流程名称
			a.util.createWFTitle(b,x,a.config.title);
			
			a.config.panelSize={
				width:_w,
				height:_h
			};
		}
		// 初始化图例
		a.util.createTuLi(b,x);
		
		if(r.restore &&r.restore.position){
			b.extend(true, a.config.position, r.restore.position);
		}
		
		var y = Raphael(x, _w, _h);
		
		b(y).attr("fill","url("+a.config.basePath+"img/bg.png)");
		
		b(y).bind("removeElement",function(){
			var j = b(y).data("mousedownNode");
			if (j) {
				if (j.getId().substring(0, 4) == "rect") {
					b(y).trigger("removerect", j)
				} else {
					if (j.getId().substring(0, 4) == "path") {
						b(y).trigger("removepath", j)
					}
				}
				b(y).removeData("currNode")
			}
		});
		b(document).keydown(function(i) {
			if (!a.config.editable) {
				return
			}
			var active = document.activeElement;
			if(active && active.nodeName=="INPUT"){
				return true;
			}
			if (i.keyCode == 46) {
				b(y).trigger("removeElement");
			}
		});
		b(x).click(function() {
			b(y).data("currNode", null);
			b(y).trigger("click", {
				getId : function() {
					return "00000000"
				},
				getFormType:function(){
					return a.config.props.props.projtype.value;
				}
			});
			 b(y).trigger("showprops", [ a.config.props.props, {
				 getId : function() {
					 return "00000000"
				 },
				 getFormType:function(){
					return a.config.props.props.projtype.value;
				 }
			 }])
		});
		b(y).bind("initFormType", function(r, o, p,_t) {
			if(_t=="projtype"){
				$("#pformTemplate select").click();
			}			
		});
		b(y).bind("changeFormType", function(r, o, p,_t) {
			if(_t=="projtype"){
				_props.freshByUI();
				alert("主对象类型已改变，请调整相关的属性。");
			}
		});
		var w = function(c, i) {
			if (!a.config.editable) {
				return
			}
			if (i.getId().substring(0, 4) == "rect") {
				q[i.getId()] = null;
				i.remove()
			} else {
				if (i.getId().substring(0, 4) == "path") {
					g[i.getId()] = null;
					i.remove()
				}
			}
		};
		b(y).bind("removepath", w);
		b(y).bind("removerect", w);
		b(y).bind("addrect", function(j, c, k) {
			var i = new a.rect(b.extend(true, {}, a.config.tools.states[c], k), y,x);
			q[i.getId()] = i
		});
		var f = function(i, k, j) {
			if(g){
				var from=k.getId();
				var to=j.getId();
				for(var id in g){
					try {
						var _p=g[id];
						if(_p.from().getId()==from && _p.to().getId()==to){
							return;
						}
					} catch (e) {
					}
				}
			}
			var c = new a.path({}, y, k, j);
			g[c.getId()] = c;
			// $("#pointer").click();
		};
		var _s=function(){
			// 刷新最后的显示的属性
			b(y).trigger("saveprops");
			
			a.config.position.minX=1000;
			a.config.position.minY=1000;
			a.config.position.maxX=0;
			a.config.position.maxY=0;
			var i = "{";
			i += "'states':{";
			for ( var c in q) {
				if (q[c]) {
					i += "'"+q[c].getId() + "':" + q[c].toJson() + ","
				}
			}
			if (i.substring(i.length - 1, i.length) == ",") {
				i = i.substring(0, i.length - 1)
			}
			i += "}";
			i += ",";
			i += "'paths':{";
			for ( var c in g) {
				if (g[c]) {
					i +="'"+ g[c].getId() + "':" + g[c].toJson() + ","
				}
			}
			if (i.substring(i.length - 1, i.length) == ",") {
				i = i.substring(0, i.length - 1)
			}
		    i+="}";
	    	i += ",'props':{'props':{";
	    	 for ( var c in a.config.props.props) {
	    		var val=a.config.props.props[c].value;
				if(typeof val=="object"){
					i += "'"+c + "':{'value':" + myUtil.jsonArrayToString(val)+ "},"
				}else{
					i += "'"+c + "':{'value':'" + val+ "'},"
				}
	    	 }
	    	 if (i.substring(i.length - 1, i.length) == ",") {
	    	 i = i.substring(0, i.length - 1)
	    	 }
	    	 i += "}}";
	    	i+=",'position':"+myUtil.jsonToString(a.config.position); 
		   i+="}";
		   a.config.tools.save.onclick(i)
		};
		b(y).bind("addpath", f);
		b(y).bind("saveWorkFlow", _s);
		b(y).data("mod", "pointer");
		if (a.config.editable) {
			b("#myflow_tools").draggable({
				handle : "#myflow_tools_handle"
			}).css(a.config.tools.attr);
			b("#myflow_tools .node").hover(function() {
				b(this).addClass("mover")
			}, function() {
				b(this).removeClass("mover")
			});
			b("#myflow_tools .selectable").click(function() {
				b(".selected").removeClass("selected");
				b(this).addClass("selected");
				b(y).data("mod", this.id)
				if(this.id=="pointer"){
					b(x).removeClass("cursor-line");
				}else{
					b(x).addClass("cursor-line");
				}
			});
			b("#myflow_tools .state").each(function() {
				b(this).draggable({
					zIndex : 999999,
					helper : "clone",
					start : function(c, i) {
						i.helper.width($(this).width());
					}
				})
			});
			b(x).droppable({
				accept : ".state",
				drop : function(c, i) {
					b(y).trigger("addrect", [ i.helper.attr("type"), {
						attr : {
							x : i.helper.offset().left-a.config.offsetX+x.scrollLeft,
							y : i.helper.offset().top-a.config.offsetY+x.scrollTop
						}
					} ])
				}
			});
			b("#myflow_save").unbind().bind("click",function() {
				b(y).trigger("saveWorkFlow");
			});

			// 添加双击和右键事件
			var citem=[];
			$("#myflow_tools .state").each(function(){
				var type=$(this).attr("type");
				citem.push({
					id:"add_"+$(this).attr("type"),
					text:"添加"+$(this).find(".text").text(),
					icon:$(this).find("img").attr("src"),
					action:function(e){
						b(y).trigger("addrect", [type, {
							attr : {
								x : e.pageX-a.config.offsetX,
								y : e.pageY-a.config.offsetY
							}
						} ])
					}
				});
			});
			b(x).dblclick(function(){
				if($("#path").hasClass("selected")){
					$("#pointer").click();
				}else{
					$("#path").click();
				}
			}).WinContextMenu({
				items:[{
					id:'add',
					text:'添加步骤',
					icon:a.config.basePath+"/img/add.png",
					items:citem
				},{
					split:true
				},{
					id:'save',
					text:'保存',
					icon:a.config.basePath+"/img/save.png",
					action:function(e){
						b(y).trigger("saveWorkFlow");
					}
				},{
					split:true
				},{
					id:'selected',
					text:'选择',
					icon:a.config.basePath+"/img/select16.gif",
					action:function(e){
						$("#pointer").click();
					}
				},{
					id:'line',
					text:'连接',
					icon:a.config.basePath+"/img/line.png",
					action:function(e){
						$("#path").click();
						var j = b(y).data("mousedownNode");
						j.mousedown();
					}
				},{
					split:true
				},{
					id:'delete',
					text:'删除',
					icon:a.config.basePath+"/img/remove.png",
					action:function(e){
						if(confirm("确定删除？")){
							b(y).trigger("removeElement");
						}
						myUtil.stopPropagation(e);
						return false;
					}
				},{
					id:'clear',
					text:'清空',
					icon:a.config.basePath+"/img/remove.png",
					action:function(e){
						if(confirm("确定清空？")){
							rebuild();
						}
					}
				}]
			});
			_props=new a.props({}, y)
		}else{
			b("#myflow_tools").hide();
			b("#myflow_props").hide();
		}
		if (r.restore) {
			var B = r.restore;
			var z = {};
			if (B.states) {
				for ( var s in B.states) {
					B.states[s]["id"]=s;
					var d = new a.rect(b.extend(true, {}, a.config.tools.states[B.states[s].type], B.states[s]), y,x);
					d.restore(B.states[s]);
					z[s] = d;
					q[d.getId()] = d
				}
			}
			if (B.paths) {
				for ( var s in B.paths) {
					B.paths[s]["id"]=s;
					var n = new a.path(b.extend(true, {}, a.config.tools.path, B.paths[s]), y, z[B.paths[s].from], z[B.paths[s].to]);
					n.restore(B.paths[s]);
					g[n.getId()] = n
				}
			}
		}
		var A = a.config.historyRects, l = a.config.activeRects,S=a.config.subRects,R=a.config.abendRects;
		if (A.rects.length || l.rects.length|| S.rects.length || R.rects.length) {
			var m = {}, z = {};
			// 遍历设计的步骤，组织数据给重绘使用
			var noPath=true;
			for ( var h in g) {
				noPath=false;
				if (!z[g[h].from().getId()]) {
					z[g[h].from().getId()] = {
						rect : g[h].from(),
						paths : {}
					}
				}
				z[g[h].from().getId()].paths[g[h].getId()] = g[h];
				if (!z[g[h].to().getId()]) {
					z[g[h].to().getId()] = {
						rect : g[h].to(),
						paths : {}
					}
				}
			}
			// 如果没有路径,表示只有一个节点
			if(noPath){
				for(var i in q){
					z[i]={
						rect:q[i],
						paths:{}
					};
				}
			}
			// 重绘历史步骤
			for (var u = 0; u < A.rects.length; u++) {
				if (z[A.rects[u].name]) {
					var rect=z[A.rects[u].name].rect;
					rect.attr(A.rectAttr);
					rect.textAttr(A.textAttr);
					rect.setWFType("history");
				}
				for (var t = 0; t < A.rects[u].paths.length; t++) {
					try {
						if (z[A.rects[u].name].paths[A.rects[u].paths[t]]) {
							z[A.rects[u].name].paths[A.rects[u].paths[t]].attr(A.pathAttr)
						}
					} catch (e) {
						
					}
				}
			}
			// 重绘当前步骤
			for (var u = 0; u < l.rects.length; u++) {
				if (z[l.rects[u].name]) {
					var rect=z[l.rects[u].name].rect;
					rect.attr(l.rectAttr);
					rect.textAttr(A.textAttr);
					rect.setWFType("active");
				}
				for (var t = 0; t < l.rects[u].paths.length; t++) {
					try {
						if (z[l.rects[u].name].paths[l.rects[u].paths[t]]) {
							z[l.rects[u].name].paths[l.rects[u].paths[t]].attr(l.pathAttr)
						}
					} catch (e) {
					}
				}
			}
			// 重绘错误步骤
			for (var u = 0; u < R.rects.length; u++) {
				if (z[R.rects[u].name]) {
					var rect=z[R.rects[u].name].rect;
					rect.attr(R.rectAttr);
					rect.textAttr(A.textAttr);
					rect.setWFType("cancel");
				}
				for (var t = 0; t < R.rects[u].paths.length; t++) {
					try {
						if (z[R.rects[u].name].paths[R.rects[u].paths[t]]) {
							z[R.rects[u].name].paths[R.rects[u].paths[t]].attr(R.pathAttr)
						}
					} catch (e) {
					}
				}
			}
			// 重绘子步骤
			for (var u = 0; u < S.rects.length; u++) {
				if (z[S.rects[u].name]) {
					var rect=z[S.rects[u].name].rect;
					rect.rebuildSub(S.rects[u]);
				}
			}
		}
		// 触发显示流程信息
		b(x).click();
	};
	b.fn.myflow = function(c) {
		return this.each(function() {
			b(this).empty();
			a.init(this, c)
		})
	};
	b.myflow = a
})(jQuery);